// ICFPLambdaLifting.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include "Map.h"
#include "Plan.h"
#include "Search.h"
#include <fstream>

int Map::nRows;
int Map::nColumns;
size_t Node::nextID = 0;

const Map* parseMap(std::istream& in);

int main(int argc, char* argv[])
{
	std::ifstream myReadFile = std::ifstream ("./Maps/contest11.map");
  if (!myReadFile)
    throw std::exception("Could not read input file.");
	boost::shared_ptr<const Map> initialMap = boost::shared_ptr<const Map>(parseMap(myReadFile));
	//boost::shared_ptr<const Map> initialMap(parseMap(std::cin));

   
  // Successors
  std::cout << "Successors" << std::endl;
  SuccessorUtils::PrintSuccessors(initialMap);
  
  Map* copy = initialMap->copy();
  copy->DisplayInfos();


  // Update
  std::cout << std::endl;
  std::cout << "Update" << std::endl;

	copy->update();
	std::cout << *copy;


  // Move
  std::cout << std::endl;
  std::cout << "Move" << std::endl;
  int points = 0;
  MapUtils::Move(*copy, 1, false, points);
  copy->DisplayInfos();
  /*
  
  // Search
	DepthFirstSearch searchAlgorithm(initialMap);
  
  //BreadthFirstSearch searchAlgorithm(initialMap);
  
	boost::shared_ptr<const Plan> plan = searchAlgorithm.search();
  
  
	std::cout << "Plan: " << *plan << std::endl;
  */
  std::getchar();
  return 0;
}

const Map* parseMap(std::istream& in)
{
	std::vector<std::string> rows;
	std::string buffer;
	size_t max = 0;
	while (!getline(in, buffer).eof())
	{
			rows.insert(rows.begin(), buffer);
			max = std::max(max, buffer.size());
	}
	if (rows.empty())
		throw std::exception("No rows");

	for (auto it = rows.begin(); it != rows.end(); ++it)
	{
		it->insert(it->size(), max - it->size(), '#');
		assert(it->size() == max);
	}

	char* squares = new char[rows.size() * rows.back().size()];
	int nSquare = 0;
		
	for(size_t i = 0; i < rows.size(); ++i)
	{
		for (size_t j = 0; j < rows[i].length(); ++j)
		{
			squares[nSquare++] = rows[i][j];
		}
	}
	
  Map::nRows = rows.size();
  Map::nColumns = rows.back().size();

	return new Map(squares);
}
